﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Web;

namespace Apodidae.Common
{
    public class Utilies
    {
        #region 字符串操作相关

        public static string GetSubString(string originalString, int length, string afterSymbol)
        {
            if (string.IsNullOrEmpty(originalString) || originalString.Length <= length)
                return originalString;

            return originalString.Substring(0, length) + afterSymbol;
        }

        #endregion

        #region POST数据

        /// <summary>
        /// 远程执行抛数据请求
        /// </summary>
        /// <param name="url">远程请求的网址</param>
        /// <param name="paras">抛送的数据</param>
        /// <returns>远程执行完，返回的结果</returns>
        public static string ExecuteDoPost(string url, string paras)
        {
            //参数不完整，不处请求处理
            if (string.IsNullOrEmpty(url) || string.IsNullOrEmpty(paras))
                return "";

            Stream newStream = null;
            HttpWebRequest myRequest = null;

            try
            {
                byte[] data = Encoding.UTF8.GetBytes(paras);
                myRequest = (HttpWebRequest)WebRequest.Create(url);

                myRequest.Method = "POST";
                myRequest.ContentType = "application/x-www-form-urlencoded";
                myRequest.ContentLength = data.Length;
                myRequest.Timeout = 600000;

                newStream = myRequest.GetRequestStream();

                // Send the data.  
                newStream.Write(data, 0, data.Length);
                newStream.Close();

                HttpWebResponse myResponse = (HttpWebResponse)myRequest.GetResponse();
                StreamReader reader = new StreamReader(myResponse.GetResponseStream(), Encoding.UTF8);
                string content = reader.ReadToEnd();


                /*dispose*/
                newStream.Dispose();
                myRequest.Abort();

                return content;
            }
            catch
            {
                if (newStream != null)
                    newStream.Dispose();

                if (myRequest != null)
                    myRequest.Abort();
            }

            return "";
        }

        #endregion

        #region IP地址相关
        /// <summary>
        /// 验证是否是内网ip
        /// </summary>
        /// <param name="ip"></param>
        /// <returns></returns>
        public static bool IsInsideIp(string ip)
        {
            //A类 10.0.0.0 --10.255.255.255
            //B类 172.16.0.0--172.31.255.255
            //C类 192.168.0.0--192.168.255.255
            string AIp = @"10\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])";
            string BIp = @"172\.(1[6-9]|2\d|3[0-1])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])";
            string CIp = @"192\.168\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])";
            if (Regex.IsMatch(ip, AIp))
            {
                return true;
            }
            if (Regex.IsMatch(ip, BIp))
            {
                return true;
            }
            if (Regex.IsMatch(ip, CIp))
            {
                return true;
            }

            return false;
        }

        /// <summary>
        /// 判断是否是正确的ip格式
        /// </summary>
        /// <param name="str1"></param>
        /// <returns></returns>
        public static bool IsIPAddress(string str1)
        {
            if (str1 == null || str1 == string.Empty || str1.Length < 7 || str1.Length > 15) return false;
            string regformat = @"(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])";
            Regex regex = new Regex(regformat, RegexOptions.IgnoreCase);
            return regex.IsMatch(str1);
        }

        /// <summary>
        /// 获取web客户端ip
        /// </summary>
        /// <returns></returns>
        public static string GetWebClientIp()
        {
            if (HttpContext.Current == null
                || HttpContext.Current.Request == null
                || HttpContext.Current.Request.ServerVariables == null)
                return "";

            string CustomerIP = "";

            //CDN加速后取到的IP
            CustomerIP = HttpContext.Current.Request.Headers["Cdn-Src-Ip"];
            if (!string.IsNullOrEmpty(CustomerIP))
            {
                return CustomerIP;
            }

            if (HttpContext.Current.Request.ServerVariables["HTTP_VIA"] != null)
            {
                CustomerIP = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
                if (CustomerIP == null)
                    CustomerIP = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
            }
            else
            {
                CustomerIP = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];

            }

            if (string.Compare(CustomerIP, "unknown", true) == 0)
                return HttpContext.Current.Request.UserHostAddress;
            return CustomerIP;
            /** lcq
            关键就在HTTP_X_FORWARDED_FOR
            使用不同种类代理服务器，上面的信息会有所不同：

            一、没有使用代理服务器的情况：
            REMOTE_ADDR = 您的 IP
            HTTP_VIA = 没数值或不显示
            HTTP_X_FORWARDED_FOR = 没数值或不显示

            二、使用透明代理服务器的情况：Transparent Proxies
            REMOTE_ADDR = 代理服务器 IP 
            HTTP_VIA = 代理服务器 IP
            HTTP_X_FORWARDED_FOR = 您的真实 IP
            这类代理服务器还是将您的信息转发给您的访问对象，无法达到隐藏真实身份的目的。

            三、使用普通匿名代理服务器的情况：Anonymous Proxies
            REMOTE_ADDR = 代理服务器 IP 
            HTTP_VIA = 代理服务器 IP
            HTTP_X_FORWARDED_FOR = 代理服务器 IP
            隐藏了您的真实IP，但是向访问对象透露了您是使用代理服务器访问他们的。

            四、使用欺骗性代理服务器的情况：Distorting Proxies
            REMOTE_ADDR = 代理服务器 IP 
            HTTP_VIA = 代理服务器 IP 
            HTTP_X_FORWARDED_FOR = 随机的 IP
            告诉了访问对象您使用了代理服务器，但编造了一个虚假的随机IP代替您的真实IP欺骗它。

            五、使用高匿名代理服务器的情况：High Anonymity Proxies (Elite proxies)
            REMOTE_ADDR = 代理服务器 IP
            HTTP_VIA = 没数值或不显示
            HTTP_X_FORWARDED_FOR = 没数值或不显示 
            **/
        }

        /// <summary>
        /// 获取web客户端代理ip
        /// </summary>
        /// <returns></returns>
        public static string GetWebClientProxyIp()
        {
            if (HttpContext.Current == null
                || HttpContext.Current.Request == null
                || HttpContext.Current.Request.ServerVariables == null)
                return "";

            string CustomerProxyIP = "";

            //CDN加速后取到的IP 
            CustomerProxyIP = HttpContext.Current.Request.Headers["Cdn-Src-Ip"];
            if (!string.IsNullOrEmpty(CustomerProxyIP))
            {
                return CustomerProxyIP;
            }

            if (HttpContext.Current.Request.ServerVariables["HTTP_VIA"] != null)
            {
                CustomerProxyIP = HttpContext.Current.Request.ServerVariables["HTTP_VIA"];
            }
            return CustomerProxyIP;
        }
        #endregion

        #region 生成缩略图
        /// <summary>
        /// 生成缩略图 
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="mode"></param>
        /// <returns></returns>
        public static byte[] MakeThumbnail(byte[] buffer, int width, int height, string mode)
        {

            Stream stream = new MemoryStream(buffer);
            Bitmap originalImage = new Bitmap(stream);
            int intToWidth = width;
            int intToHeight = height;

            int x = 0;
            int y = 0;
            int intSourceWidth = originalImage.Width;
            int intSourceHeight = originalImage.Height;

            if (intSourceWidth < intToWidth)
            {
                intToWidth = intSourceWidth;
            }
            if (intSourceHeight < intToHeight)
            {
                intToHeight = intSourceHeight;
            }
            switch (mode)
            {
                case "HW"://指定高宽缩放 
                    //假如是比较宽的图片
                    if (intSourceWidth / intSourceHeight > width / height)
                    {
                        intToWidth = width;
                        intToHeight = intSourceHeight * width / intSourceWidth;
                    }//比较高的图片
                    else
                    {
                        intToHeight = height;
                        intToWidth = intSourceWidth * height / intSourceHeight;
                    }

                    break;
                case "W"://指定宽，高按比例
                    intToHeight = intSourceHeight * width / intSourceWidth;
                    break;
                case "H"://指定高，宽按比例
                    intToWidth = intSourceWidth * height / intSourceHeight;
                    break;
                case "Cut"://指定高宽裁减（不变形）
                    if ((double)originalImage.Width / (double)originalImage.Height > (double)intToWidth / (double)intToHeight)
                    {
                        intSourceHeight = originalImage.Height;
                        intSourceWidth = originalImage.Height * intToWidth / intToHeight;
                        y = 0;
                        x = (originalImage.Width - intSourceWidth) / 2;
                    }
                    else
                    {
                        intSourceWidth = originalImage.Width;
                        intSourceHeight = originalImage.Width * height / intToWidth;
                        x = 0;
                        y = (originalImage.Height - intSourceHeight) / 2;
                    }
                    break;
                default:
                    break;
            }

            //新建一个bmp图片

            Bitmap bitmap = new System.Drawing.Bitmap(intToWidth, intToHeight);

            //新建一个画板
            Graphics g = System.Drawing.Graphics.FromImage(bitmap);
            //g.DrawImage(bitmap, 0, 0);

            //设置高质量插值法
            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;

            //设置高质量,低速度呈现平滑程度
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

            //清空画布并以透明背景色填充
            g.Clear(Color.Transparent);

            //在指定位置并且按指定大小绘制原图片的指定部分
            g.DrawImage(originalImage, new Rectangle(0, 0, intToWidth, intToHeight),
                new Rectangle(x, y, intSourceWidth, intSourceHeight),
                GraphicsUnit.Pixel);
            Stream thumbnailStream = new MemoryStream();
            byte[] thumbnailBytes = null;
            try
            {
                //以jpg格式保存缩略图
                bitmap.Save(thumbnailStream, System.Drawing.Imaging.ImageFormat.Jpeg);
                thumbnailBytes = new byte[thumbnailStream.Length];
                // 设置当前流的位置为流的开始 
                thumbnailStream.Seek(0, SeekOrigin.Begin);
                //n记录实际读取数
                thumbnailStream.Read(thumbnailBytes, 0, thumbnailBytes.Length);


            }
            catch (System.Exception e)
            {
                throw e;
            }
            finally
            {
                originalImage.Dispose();
                bitmap.Dispose();
                g.Dispose();
            }

            return thumbnailBytes;
        }

        public static byte[] Thumbnail(byte[] buffer, int width, int height)
        {

            Stream stream = new MemoryStream(buffer);
            Image oldImage = Image.FromStream(stream);
            float newWidth; // 新的宽度    
            float newHeight; // 新的高度    
            float oldWidth, oldHeight; //原始高宽    
            bool flag = true;//标记图片是不是等比    
            int xPoint = 0;//若果要补白边的话，原图像所在的x，y坐标。    
            int yPoint = 0;
            //判断图片    

            oldWidth = (float)oldImage.Width;
            oldHeight = (float)oldImage.Height;

            if ((oldWidth / oldHeight) > ((float)width / (float)height)) //当图片太宽的时候    
            {
                newHeight = oldHeight * ((float)width / (float)oldWidth);
                newWidth = (float)width;
                //此时x坐标不用修改    
                yPoint = (int)(((float)height - newHeight) / 2);
                flag = false;
            }
            else if ((oldImage.Width / oldImage.Height) == ((float)width / (float)height))
            {
                newWidth = width;
                newHeight = height;
            }
            else
            {
                newWidth = (int)oldImage.Width * ((float)height / (float)oldImage.Height);  //太高的时候   
                newHeight = height;
                //此时y坐标不用修改    
                xPoint = (int)(((float)width - newWidth) / 2);
                flag = false;
            }

            //GetPhotoSize
            Size size = new Size((int)newWidth, (int)newHeight);
            //The New of Bimp Photo
            Image bitmap = new Bitmap(size.Width, size.Height);
            // The New of Palette
            Graphics g = Graphics.FromImage(bitmap);
            // Set HightQuality Arithmetic For Graphics
            g.InterpolationMode = InterpolationMode.High;
            //设置高质量,低速度呈现平滑程度
            g.SmoothingMode = SmoothingMode.HighQuality;
            //ClearCanvas
            g.Clear(System.Drawing.Color.Transparent);
            //在指定位置画图 
            g.DrawImage(oldImage, new Rectangle(0, 0, bitmap.Width, bitmap.Height),
            new System.Drawing.Rectangle(0, 0, oldImage.Width, oldImage.Height),
            GraphicsUnit.Pixel);
            // ＝＝＝缩小图片＝＝＝    
            Stream thumbnailStream = new MemoryStream();
            byte[] thumbnailBytes = null;

            if (!flag)
            {
                Bitmap bmOutput = new Bitmap(width, height);
                Graphics gc = Graphics.FromImage(bmOutput);
                SolidBrush tbBg = new SolidBrush(Color.White);
                gc.FillRectangle(tbBg, 0, 0, width, height); //填充为白色    

                //设置高质量插值法
                gc.InterpolationMode = InterpolationMode.High;

                //设置高质量,低速度呈现平滑程度
                gc.SmoothingMode = SmoothingMode.HighQuality;

                //清空画布并以透明背景色填充
                gc.Clear(System.Drawing.Color.Transparent);

                gc.DrawImage(bitmap, xPoint, yPoint, (int)newWidth, (int)newHeight);
                gc.Dispose();
                bmOutput.Save(thumbnailStream, ImageFormat.Jpeg);
                bmOutput.Dispose();
            }
            else
            {
                bitmap.Save(thumbnailStream, ImageFormat.Jpeg);
            }

            thumbnailBytes = new byte[thumbnailStream.Length];
            // 设置当前流的位置为流的开始 
            thumbnailStream.Seek(0, SeekOrigin.Begin);
            //n记录实际读取数
            thumbnailStream.Read(thumbnailBytes, 0, thumbnailBytes.Length);
            oldImage.Dispose();
            bitmap.Dispose();
            return thumbnailBytes;
        }



        #endregion

        #region 生成区域图

        /// <summary>
        /// 根据图片的坐标与长宽切割相应图片
        /// </summary>
        /// <param name="imgPath"></param>
        /// <param name="zoomLevel"></param>
        /// <param name="top"></param>
        /// <param name="left"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <returns></returns>
        public static byte[] ImageCrop(System.Drawing.Image img, int top, int left, int width, int height)
        {
            Bitmap bitmap = new Bitmap(width, height);
            Graphics g = Graphics.FromImage(bitmap);
            g.DrawImage(img, new Rectangle(0, 0, width, height), new Rectangle(left, top, width, height), GraphicsUnit.Pixel);
            MemoryStream ms = new MemoryStream();
            byte[] buffer = null;
            bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
            buffer = new byte[ms.Length];
            // 设置当前流的位置为流的开始 
            ms.Seek(0, SeekOrigin.Begin);
            //n记录实际读取数
            ms.Read(buffer, 0, buffer.Length);
            img.Dispose();
            g.Dispose();
            bitmap.Dispose();
            return buffer;
        }
        #endregion

        #region 加解密相关

        #region AES

        /// <summary>
        /// AES加密
        /// </summary>
        /// <param name="encryptString"></param>
        /// <param name="encryptKey"></param>
        /// <param name="encryptIV"></param>
        /// <returns></returns>
        public static string EncryptByAES(string encryptString, string encryptKey, string encryptIV)
        {
            encryptKey = encryptKey.PadRight(32, ' ');
            encryptKey = encryptKey.Substring(0, 32);

            encryptIV = encryptIV.PadRight(16, ' ');
            encryptIV = encryptIV.Substring(0, 16);

            RijndaelManaged rijndaelProvider = new RijndaelManaged();
            rijndaelProvider.Key = Encoding.UTF8.GetBytes(encryptKey);
            rijndaelProvider.IV = Encoding.UTF8.GetBytes(encryptIV);
            ICryptoTransform rijndaelEncrypt = rijndaelProvider.CreateEncryptor();
            byte[] inputData = Encoding.UTF8.GetBytes(encryptString);
            byte[] encryptedData = rijndaelEncrypt.TransformFinalBlock(inputData, 0, inputData.Length);
            return Convert.ToBase64String(encryptedData);
        }

        /// <summary>
        /// AES解密
        /// </summary>
        /// <param name="decryptString"></param>
        /// <param name="decryptKey"></param>
        /// <param name="encryptIV"></param>
        /// <returns></returns>
        public static string DecryptByAES(string decryptString, string decryptKey, string encryptIV)
        {
            decryptKey = decryptKey.PadRight(32, ' ');
            decryptKey = decryptKey.Substring(0, 32);

            encryptIV = encryptIV.PadRight(16, ' ');
            encryptIV = encryptIV.Substring(0, 16);

            RijndaelManaged rijndaelProvider = new RijndaelManaged();
            rijndaelProvider.Key = Encoding.UTF8.GetBytes(decryptKey);
            rijndaelProvider.IV = Encoding.UTF8.GetBytes(encryptIV);
            ICryptoTransform rijndaelDecrypt = rijndaelProvider.CreateDecryptor();
            byte[] inputData = Convert.FromBase64String(decryptString);
            byte[] decryptedData = rijndaelDecrypt.TransformFinalBlock(inputData, 0, inputData.Length);
            return Encoding.UTF8.GetString(decryptedData);
        }

        #endregion

        #region DES
        /// <summary>
        /// DES加密字符串
        /// </summary>
        /// <param name="encryptString">待加密的字符串</param>
        /// <param name="encryptKey">加密密钥,要求为8位</param>
        /// <param name="encryptIV">加密密钥,要求为8位</param>
        /// <returns>加密成功返回加密后的字符串,失败返回源串</returns>
        public static string EncryptByDES(string encryptString, string encryptKey, string encryptIV)
        {
            encryptKey = encryptKey.PadRight(8, ' ');
            encryptKey = encryptKey.Substring(0, 8);

            encryptIV = encryptIV.PadRight(8, ' ');
            encryptIV = encryptIV.Substring(0, 8);

            byte[] rgbKey = Encoding.UTF8.GetBytes(encryptKey);
            byte[] rgbIV = Encoding.UTF8.GetBytes(encryptIV);
            byte[] inputByteArray = Encoding.UTF8.GetBytes(encryptString);
            DESCryptoServiceProvider dCSP = new DESCryptoServiceProvider();
            MemoryStream mStream = new MemoryStream();
            CryptoStream cStream = new CryptoStream(mStream, dCSP.CreateEncryptor(rgbKey, rgbIV), CryptoStreamMode.Write);
            cStream.Write(inputByteArray, 0, inputByteArray.Length);
            cStream.FlushFinalBlock();
            return Convert.ToBase64String(mStream.ToArray());

        }

        /// <summary>
        /// DES解密字符串
        /// </summary>
        /// <param name="decryptString">待解密的字符串</param>
        /// <param name="decryptKey">解密密钥,要求为8位,和加密密钥相同</param>
        /// <param name="encryptIV">解密密钥,要求为8位,和加密密钥相同</param>
        /// <returns>解密成功返回解密后的字符串,失败返源串</returns>
        public static string DecryptByDES(string decryptString, string decryptKey, string encryptIV)
        {
            decryptKey = decryptKey.PadRight(8, ' ');
            decryptKey = decryptKey.Substring(0, 8);

            encryptIV = encryptIV.PadRight(8, ' ');
            encryptIV = encryptIV.Substring(0, 8);

            byte[] rgbKey = Encoding.UTF8.GetBytes(decryptKey);
            byte[] rgbIV = Encoding.UTF8.GetBytes(encryptIV);
            byte[] inputByteArray = Convert.FromBase64String(decryptString);
            DESCryptoServiceProvider DCSP = new DESCryptoServiceProvider();
            MemoryStream mStream = new MemoryStream();
            CryptoStream cStream = new CryptoStream(mStream, DCSP.CreateDecryptor(rgbKey, rgbIV), CryptoStreamMode.Write);
            cStream.Write(inputByteArray, 0, inputByteArray.Length);
            cStream.FlushFinalBlock();
            return Encoding.UTF8.GetString(mStream.ToArray());

        }

        #endregion

        #region 不可逆加密
        public static string GetMd5(string str)
        {
            return System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(str, "MD5").ToLower();
        }

        public static string GetSHA1(string str)
        {
            return System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(str, "SHA1").ToLower();
        }
        #endregion

        #endregion

        #region 类型相关
        /// <summary>
        /// 获取包含程序集名称的类型名
        /// </summary>
        /// <param name="type">类型</param>
        /// <returns></returns>
        public static string GetFullTypeName(Type type)
        {
            if (type != null && type.Assembly.FullName != null)
                return string.Format("{0},{1}", type.Assembly.FullName.Split(',')[0], type.FullName);
            else
                return string.Empty;
        }

        /// <summary>
        /// 根据包含程序集名称的类型名获取类型
        /// </summary>
        /// <param name="fullTypeName"></param>
        /// <returns></returns>
        public static Type GetType(string fullTypeName)
        {
            if (string.IsNullOrEmpty(fullTypeName) || !fullTypeName.Contains(","))
                return null;

            string[] arrs = fullTypeName.Split(',');
            Assembly assembly = Assembly.Load(arrs[0]);
            Type type = assembly.GetType(arrs[1]);
            return type;
        }
        #endregion
    }
}
